/* 
 *  Syntelos XB
 *  Copyright (C) 2006 John Pritchard.
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License as
 *  published by the Free Software Foundation; either version 2 of
 *  the License, or (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 *  02111-1307 USA
 */

package syntelos.xb;

/** 
 * 
 * 
 * @see Attribute.Code
 * @see Attribute.Exceptions
 * @see Attribute.Synthetic
 * @see Attribute.Deprecated
 * @see Attribute.SourceFile
 * @see Attribute.ConstantValue
 * @see Attribute.InnerClasses
 * @see Attribute.LineNumberTable
 * @see Attribute.LocalVariableTable
 * @see Attribute.SourceDebugExtension
 *
 * @author John Pritchard (jdp@syntelos.com)
 */
public abstract class Attribute 
    extends Base
{
    public final static syntelos.iou.dom.Name NAME = new syntelos.iou.dom.impl.Name(ELEMENT_NODE,"http://www.syntelos.org/xb","xb:attribute");

    /** 
     * <p> Attribute name. </p>
     * 
     */
    public final static class Name
        extends syntelos.xb.Base.Attribute.Name
    {
        public final static syntelos.iou.dom.Name NAME = new syntelos.iou.dom.impl.Name(ATTRIBUTE_NODE,"http://www.syntelos.org/xb","xb:attribute.name");

        public Name(org.w3c.dom.Document doc, syntelos.iou.dom.Name name){
            super(doc,name);
        }
        public Name(org.w3c.dom.Document doc){
            this(doc,NAME);
        }
        public Name(){
            this(DOC_NIL);
        }
    }
    /*
     * TODO (base64 CF)
     */
    public static class Any 
        extends syntelos.xb.Attribute
    {
        public final static syntelos.iou.dom.Name NAME = new syntelos.iou.dom.impl.Name(ELEMENT_NODE,"http://www.syntelos.org/xb","xb:attribute.any");

        public Any(org.w3c.dom.Document doc, syntelos.iou.dom.Name name){
            super(doc,name);
        }
        public Any(org.w3c.dom.Document doc){
            this(doc,NAME);
        }
        public Any(){
            this(DOC_NIL);
        }
        public syntelos.iou.dom.Node compile(){
            /*
             * Write CF into base64 CF
             */
            throw new Error.Bug("TODO (write base64 CF)");
        }
        public syntelos.iou.dom.Node decompile(){
            /*
             * Read base64 child-text into CF
             */
            throw new Error.Bug("TODO (read base64 CF)");
        }
        public int atlen(){
            byte[] cf = this.getCF();
            int cf_len = (null == cf)?(0):(cf.length);
            return (4 + cf_len);
        }
        public void readCF(IO.Uri src, CF.Reader reader)
            throws java.io.IOException
        {
            int cf_len = reader.readInt();
            byte[] cf = null;
            if (0 < cf_len){
                cf = new byte[cf_len];
                reader.readFully(cf,0,cf_len);
            }
            this.setCF(cf);
        }
        public void writeCF(IO.Uri dst, CF.Writer writer)
            throws java.io.IOException
        {
            this.getAttributeName().writeCF(dst,writer);
            //
            byte[] cf = this.getCF();
            int cf_len = (null == cf)?(0):(cf.length);
            writer.writeInt(cf_len);
            if (0 < cf_len)
                writer.write(cf,0,cf_len);
        }
    }
    /**
     * Attribute with no load.
     */
    public abstract static class Empty
        extends syntelos.xb.Attribute
    {
        public Empty(org.w3c.dom.Document doc, syntelos.iou.dom.Name name){
            super(doc,name);
        }

        public final int atlen(){
            return 0;
        }
        public final void readCF(IO.Uri src, CF.Reader reader)
            throws java.io.IOException
        {
            if (this.atlen() != reader.readInt())
                throw new Error.Format("Attribute not empty.");
            else
                return;
        }
        public final void writeCF(IO.Uri dst, CF.Writer writer)
            throws java.io.IOException
        {
            this.getAttributeName().writeCF(dst,writer);
            int at_len = this.atlen();
            writer.writeInt(at_len);
        }
    }
    

    private byte[] cf;

    public Attribute(org.w3c.dom.Document doc, syntelos.iou.dom.Name name){
        super(doc,name);
    }
    public Attribute(org.w3c.dom.Document doc){
        this(doc,NAME);
    }
    public Attribute(){
        this(DOC_NIL);
    }

    protected byte[] getCF(){
        return this.cf;
    }
    protected void setCF(byte[] cf){
        this.cf = cf;
    }

    public final Attributes getAttributesParent(){
        return (Attributes)this.getParentNode();
    }

    public final syntelos.xb.Attribute.Name getAttributeName(){
        syntelos.xb.Attribute.Name name = (syntelos.xb.Attribute.Name)this.getAttributeNode(syntelos.xb.Attribute.Name.NAME);
        if (null == name){
            name = new syntelos.xb.Attribute.Name();
            this.setAttributeNode(name);
        }
        return name;
    }
    public final void setAttributeName(int cpx){
        this.getAttributeName().setAttributeName(cpx);
    }
    public final void setAttributeName(String name){
        this.getAttributeName().setAttributeName(name);
    }
    public final void setAttributeName(CF.Constants.Utf8 name){
        this.getAttributeName().setAttributeName(name);
    }

    /**
     * @return Attribute length in CF terms: an attribute is a 16bit
     * (u2) CP `index' to its name string, a 31bit (u4) `length', and
     * then length- many bytes.
     */
    public abstract int atlen();

    public abstract void readCF(IO.Uri src, CF.Reader reader)
        throws java.io.IOException;

    public abstract void writeCF(IO.Uri dst, CF.Writer writer)
        throws java.io.IOException;

}
